package org.ciallo.simplemusicplayer.data.repository;

import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.MediaScannerConnection;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;
import org.ciallo.simplemusicplayer.R;
import org.ciallo.simplemusicplayer.activity.MainActivity;
import org.ciallo.simplemusicplayer.data.AppDatabase;
import org.ciallo.simplemusicplayer.data.dao.*;
import org.ciallo.simplemusicplayer.data.model.*;
import org.ciallo.simplemusicplayer.util.Constants;
import org.ciallo.simplemusicplayer.util.MediaStoreUtil;
import org.ciallo.simplemusicplayer.util.PermissionUtil;
import org.ciallo.simplemusicplayer.util.PinyinUtil;
import timber.log.Timber;

import java.io.File;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @author Jukomu
 * @Description: 歌曲相关数据的仓库类
 * 负责协调来自不同数据源（如Room数据库、网络）的歌曲数据
 * @Package: org.ciallo.simplemusicplayer.data.repository
 * @Project: SimpleMusicPlayer
 * @name: SongRepository
 * @Date: 2025/5/29-05:13
 * @Filename: SongRepository
 */
public class SongRepository {

    private final FavoriteSongDao favoriteSongDao;
    private final SongDao songDao;
    private final RecentlyPlayedDao recentlyPlayedDao;
    private final PlaylistDao playlistDao;
    private final ExecutorService databaseWriteExecutor;
    private final Context applicationContext; // 用于 MediaStoreUtil
    private final Application application; // 修改为 Application 类型
    private final PlayCountDao playCountDao;

    // LiveData 用于通知UI扫描状态
    private final MutableLiveData<Boolean> _isScanning = new MutableLiveData<>(false);
    public final LiveData<Boolean> isScanning = _isScanning;

    // 原子布尔值，用于防止同时发起多个扫描任务
    private final AtomicBoolean scanningInProgress = new AtomicBoolean(false);

    // --- 通知相关常量 ---
    private static final String SCAN_NOTIFICATION_CHANNEL_ID = "scan_music_channel";
    private static final String SCAN_NOTIFICATION_CHANNEL_NAME = "音乐扫描服务";
    private static final int SCAN_NOTIFICATION_ID = 1002; // 与播放通知ID区分


    /**
     * 构造函数。
     *
     * @param application Application实例，用于获取数据库和上下文
     */
    public SongRepository(Application application) {
        AppDatabase database = AppDatabase.getDatabase(application);
        this.applicationContext = application.getApplicationContext(); // 保存上下文
        this.application = application; // 保存Application实例
        favoriteSongDao = database.favoriteSongDao();
        songDao = database.songDao();
        recentlyPlayedDao = database.recentlyPlayedDao();
        playlistDao = database.playlistDao();
        databaseWriteExecutor = AppDatabase.databaseWriteExecutor;
        playCountDao = database.playCountDao();
        createScanNotificationChannel(); // 创建通知渠道
    }

    // --- 通知栏相关方法 ---
    private void createScanNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = SCAN_NOTIFICATION_CHANNEL_NAME;
            String description = "用于显示音乐扫描进度的通知";
            int importance = NotificationManager.IMPORTANCE_LOW; // 低优先级，避免声音
            NotificationChannel channel = new NotificationChannel(SCAN_NOTIFICATION_CHANNEL_ID, name, importance);
            channel.setDescription(description);
            channel.setSound(null, null); // 无声音
            channel.enableVibration(false); // 无震动
            NotificationManager notificationManager = application.getSystemService(NotificationManager.class);
            if (notificationManager != null) {
                notificationManager.createNotificationChannel(channel);
            }
        }
    }

    /**
     * 显示或更新扫描通知。
     * @param title 标题
     * @param text 内容文本
     * @param isAutoCancel 完成后是否自动取消（或需要用户点击）
     */
    private void showScanNotification(String title, String text, boolean indeterminate, boolean isAutoCancel) {
        if (!PermissionUtil.hasNotificationPermission(application)) return; // 再次检查

        Intent intent = new Intent(application, MainActivity.class); // 点击通知返回主界面
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(application, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(application, SCAN_NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_sync) // 需要一个扫描/同步图标
                .setContentTitle(title)
                .setContentText(text)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setOngoing(!isAutoCancel) // 如果不是自动取消，则设为正在进行（用户不能滑动清除）
                .setAutoCancel(isAutoCancel) // 如果是完成/错误通知，设为可自动取消或点击取消
                .setContentIntent(pendingIntent) // 点击通知的操作
                .setOnlyAlertOnce(true); // 避免重复提示音（虽然我们设置了无声）

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(application);
        try {
            notificationManager.notify(SCAN_NOTIFICATION_ID, builder.build());
        } catch (SecurityException e) {
            Timber.e(e, "Failed to show scan notification due to SecurityException (missing POST_NOTIFICATIONS permission?)");
            // 这里可以考虑给用户一个更直接的提示去开启通知权限，或者记录下来
        }
    }

    private void updateScanNotification(String title, String text, boolean indeterminate, boolean isAutoCancel) {
        showScanNotification(title, text, indeterminate, isAutoCancel); // 更新通知本质上是重新发送一个相同ID的通知
    }

    private void cancelScanNotification() {
        if (!PermissionUtil.hasNotificationPermission(application)) return;
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(application);
        try {
            notificationManager.cancel(SCAN_NOTIFICATION_ID);
        } catch (SecurityException e) {
            Timber.e(e, "Failed to cancel scan notification due to SecurityException.");
        }
    }


    // --- Song Operations (来自 SongDao) ---
    public void insertSong(Song song) {
        databaseWriteExecutor.execute(() -> songDao.insertSong(song));
    }

    public void insertAllSongs(List<Song> songs) {
        databaseWriteExecutor.execute(() -> songDao.insertAllSongs(songs));
    }

    public void updateSong(Song song) {
        databaseWriteExecutor.execute(() -> songDao.updateSong(song));
    }

    public void deleteSong(Song song) {
        databaseWriteExecutor.execute(() -> songDao.deleteSong(song));
    }

    public void deleteAllSongsFromDB() { // 避免与 Controller/Service 的 clearQueue 混淆
        databaseWriteExecutor.execute(songDao::deleteAllSongs);
    }

    public LiveData<Song> getSongById(long songId) {
        return songDao.getSongById(songId);
    }

    public LiveData<List<Song>> getAllSongsSortedByPinyin() {
        return songDao.getAllSongsSortedByPinyin();
    }

    public LiveData<List<Song>> getAllSongsSortedByDateAdded() {
        return songDao.getAllSongsSortedByDateAdded();
    }

    /**
     * 根据ID从数据库中删除一首歌曲。
     *
     * @param songId 要删除的歌曲ID。
     */
    public void deleteSongById(long songId) {
        databaseWriteExecutor.execute(() -> {
            songDao.deleteSongById(songId);
            Timber.i("Song with ID %d deleted from database.", songId);
        });
    }

    public LiveData<List<Song>> getSongsFilteredOrAllSortedByPinyin(@Nullable String query) { // 这个是你单曲列表用的
        if (query == null || query.trim().isEmpty()) {
            return songDao.getAllSongsSortedByPinyin();
        } else {
            String searchQueryWithWildcards = "%" + query.trim() + "%";
            // 使用 getAllSongsOrSearchSortedByPinyin，或者如果你在DAO中保留了 searchSongs 也可以
            return songDao.searchSongs(searchQueryWithWildcards); // 假设 searchSongs 是你用于单曲过滤的方法
        }
    }

    // --- MediaStore Scanning ---

    /**
     * 从设备的 MediaStore 异步扫描歌曲，并以增量方式更新到本地数据库。
     * 显示扫描过程的通知。
     */
    public void refreshSongsFromMediaStore() {
        if (!PermissionUtil.hasNotificationPermission(application)) { // <--- 检查通知权限
            // 如果没有通知权限，可以考虑不显示通知，或者提示用户（但不阻塞扫描）
            Timber.w("Notification permission not granted. Scan notification will not be shown.");
            // 仍然可以继续扫描，只是不显示通知
            // 如果希望强制用户授权，可以在UI层处理权限请求
        }

        if (scanningInProgress.compareAndSet(false, true)) {
            _isScanning.postValue(true);
            Timber.i("User triggered refresh: Starting comprehensive media scan...");
            showScanNotification("准备扫描文件系统...", "初始化...", true, false);

            databaseWriteExecutor.execute(() -> {
                int songsProcessedInPhase2 = 0;
                try {
                    // --- 阶段一：主动文件系统扫描 ---
                    List<File> rootScanDirectories = getRootScanDirectoriesFromDbAndDefaults(); // <--- 修改: 从DB和默认获取

                    if (!rootScanDirectories.isEmpty()) {
                        List<String> allFilesToRequestScan = new ArrayList<>();
                        int filesScannedCounter = 0; // 用于更新通知
                        int totalFilesToRequest = 0; // 只是用于大致的进度感觉

                        for (File rootDir : rootScanDirectories) {
                            if (rootDir == null || !rootDir.exists() || !rootDir.isDirectory()) continue;
                            List<String> filesInDir = getAllAudioFilesRecursive(rootDir, 0, 2); // 限制递归深度为2
                            allFilesToRequestScan.addAll(filesInDir);
                        }
                        totalFilesToRequest = allFilesToRequestScan.size();
                        Timber.d("Phase 1: Total files to request system scan for: %d", totalFilesToRequest);

                        if (!allFilesToRequestScan.isEmpty()) {
                            final CountDownLatch scanLatch = new CountDownLatch(allFilesToRequestScan.size());
                            for (String filePath : allFilesToRequestScan) {
                                filesScannedCounter++;
                                // 更新通知 (可以节流，例如每10个文件或每秒更新一次)
                                if (filesScannedCounter % 20 == 0 || filesScannedCounter == totalFilesToRequest) {
                                    File parentFile = new File(filePath).getParentFile();
                                    String currentDirName = parentFile != null ? parentFile.getName() : "未知目录";
                                    updateScanNotification("扫描文件夹: " + currentDirName,
                                            "已请求扫描 " + filesScannedCounter + "/" + totalFilesToRequest + " 文件", true, false);
                                }

                                MediaScannerConnection.scanFile(
                                        application,
                                        new String[]{filePath},
                                        null,
                                        (path, uri) -> {
                                            Timber.v("System scan acknowledged for: %s, URI: %s", path, uri);
                                            scanLatch.countDown();
                                        }
                                );
                            }
                            boolean allScansAcknowledged = scanLatch.await(3, TimeUnit.MINUTES); // 调整超时
                            if (allScansAcknowledged) {
                                Timber.i("Phase 1: All file scan requests acknowledged by MediaScannerConnection.");
                            } else {
                                Timber.w("Phase 1: Timeout or interruption waiting for all file scan requests.");
                            }
                            // 短暂等待 MediaStore 处理
                            try { Thread.sleep(3000); } catch (InterruptedException ignored) {}
                        }
                    }

                    // --- 阶段二：从 MediaStore 同步到 Room ---
                    updateScanNotification("正在从媒体库同步...", "整理歌曲信息...", true, false);
                    songsProcessedInPhase2 = performMediaStoreToRoomSync(); // 这个方法已在之前实现（增量更新）

                    updateScanNotification("扫描完成", songsProcessedInPhase2 + " 首歌曲已同步", false, true);

                } catch (Exception e) {
                    Timber.e(e, "Error during comprehensive media scan.");
                    updateScanNotification("扫描出错", "请稍后重试", false, true);
                } finally {
                    _isScanning.postValue(false);
                    scanningInProgress.set(false);
                    Timber.i("Comprehensive media scan finished.");
                    new Handler(Looper.getMainLooper()).postDelayed(this::cancelScanNotification, 7000); // 稍长一点时间
                }
            });
        } else {
            Timber.i("MediaStore scan already in progress. Ignoring new request.");
            Toast.makeText(application, "扫描已在进行中", Toast.LENGTH_SHORT).show();
        }
    }

    private List<File> getRootScanDirectoriesFromDbAndDefaults() {
        Set<File> dirs = new LinkedHashSet<>(); // 使用Set避免重复

        // 1. 从数据库中已有的歌曲获取其所在文件夹
        List<String> existingFolderPaths = songDao.getDistinctFolderPaths();
        if (existingFolderPaths != null) {
            for (String path : existingFolderPaths) {
                if (path != null && !path.isEmpty()) {
                    File dir = new File(path);
                    if (dir.exists() && dir.isDirectory()) {
                        dirs.add(dir);
                    }
                }
            }
            Timber.d("Found %d existing song folders from DB to pre-scan.", dirs.size());
        }

        // 2. 添加标准的 Music 和 Downloads 目录
        File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
        if (musicDir != null && musicDir.exists() && musicDir.isDirectory()) dirs.add(musicDir);
        File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        if (downloadsDir != null && downloadsDir.exists() && downloadsDir.isDirectory()) dirs.add(downloadsDir);

        // (未来可以添加用户自定义目录)
        List<File> resultList = new ArrayList<>(dirs);
        Timber.d("Total unique root directories for pre-scan: %d -> %s", resultList.size(),
                resultList.stream().map(File::getName).collect(Collectors.joining(", ")));
        return resultList;
    }

    private List<String> getAllAudioFilesRecursive(File directory, int currentDepth, int maxDepth) {
        List<String> audioFiles = new ArrayList<>();
        if (directory == null || !directory.exists() || !directory.isDirectory() || currentDepth > maxDepth) {
            return audioFiles;
        }
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    audioFiles.addAll(getAllAudioFilesRecursive(file, currentDepth + 1, maxDepth));
                } else {
                    String name = file.getName().toLowerCase();
                    if (name.endsWith(".mp3") || name.endsWith(".m4a") || name.endsWith(".aac") ||
                            name.endsWith(".ogg") || name.endsWith(".flac") || name.endsWith(".wav")) {
                        audioFiles.add(file.getAbsolutePath());
                    }
                }
            }
        }
        return audioFiles;
    }

    // 新的辅助方法：封装阶段二的 MediaStore 同步逻辑
    private int performMediaStoreToRoomSync() {
        // --- 这里是之前 refreshSongsFromMediaStore 中从 MediaStore 加载并进行增量更新的逻辑 ---
        List<Song> songsFromMediaStore = MediaStoreUtil.loadSongsFromMediaStore(application);
        int songsFoundInMediaStore = songsFromMediaStore.size();
        Timber.d("Phase 2: MediaStore sync found %d valid songs.", songsFoundInMediaStore);

        List<String> localSongPathsList = songDao.getAllSongPathsFromDb();
        Set<String> localSongPathsSet = new HashSet<>(localSongPathsList);

        List<Song> songsToAdd = new ArrayList<>();
        Set<String> mediaStoreSongPathsSet = new HashSet<>();

        for (Song mediaStoreSong : songsFromMediaStore) {
            mediaStoreSongPathsSet.add(mediaStoreSong.getPath());
            if (!localSongPathsSet.contains(mediaStoreSong.getPath())) {
                if (mediaStoreSong.getTitle() != null) {
                    mediaStoreSong.setTitlePinyin(PinyinUtil.getPinyin(mediaStoreSong.getTitle()));
                }
                songsToAdd.add(mediaStoreSong);
            }
        }

        if (!songsToAdd.isEmpty()) {
            songDao.insertAllSongs(songsToAdd);
            Timber.i("Phase 2: Added %d new songs to database from MediaStore.", songsToAdd.size());
        }

        List<String> pathsToDelete = new ArrayList<>();
        for (String localPath : localSongPathsList) {
            if (!mediaStoreSongPathsSet.contains(localPath)) {
                pathsToDelete.add(localPath);
            }
        }

        if (!pathsToDelete.isEmpty()) {
            int deletedCount = songDao.deleteSongsByPaths(pathsToDelete);
            Timber.i("Phase 2: Removed %d songs from database no longer in MediaStore.", deletedCount);
        }
        return songsFoundInMediaStore; // 或者返回实际处理的歌曲数
    }


    // --- Favorite Song Operations ---
    public LiveData<Boolean> isFavorite(long songId) {
        return favoriteSongDao.isFavorite(songId);
    }

    public void addToFavorites(long songId) {
        databaseWriteExecutor.execute(() -> {
            FavoriteSong favoriteSong = new FavoriteSong(songId, System.currentTimeMillis());
            favoriteSongDao.addFavorite(favoriteSong);
            Timber.d("Song ID %d added to favorites.", songId);
        });
    }

    public void removeFromFavorites(long songId) {
        databaseWriteExecutor.execute(() -> {
            favoriteSongDao.removeFavoriteBySongId(songId);
            Timber.d("Song ID %d removed from favorites.", songId);
        });
    }

    /**
     * 获取所有收藏的歌曲的完整信息。
     *
     * @return LiveData 包装的收藏歌曲列表 (包含完整的Song对象)。
     */
    public LiveData<List<Song>> getAllFavoriteSongsWithDetails() { // <--- 修改这里
        return favoriteSongDao.getAllFavoriteSongsWithDetails();
    }


    // --- Artist List Operations ---

    /**
     * 获取所有独立歌手的摘要信息 (包含ID[临时用第一个song的artistIdRoom], 名称, 歌曲数)，
     * 并处理拼音。代表性封面URI将为null。结果按歌手名拼音排序。
     *
     * @return LiveData 包装的 ArtistInfo 列表。
     */
    public LiveData<List<ArtistInfo>> getAllArtistsWithInfoSortedByPinyin() {
        // 从DAO获取所有歌曲的 LiveData (选择一个包含artistName和artistIdRoom的查询)
        LiveData<List<Song>> allSongsLiveData = songDao.getAllSongsSortedByPinyin(); // 或者一个不排序的 getAllSongs()

        return Transformations.switchMap(allSongsLiveData, songs -> {
            MutableLiveData<List<ArtistInfo>> processedArtistsLiveData = new MutableLiveData<>();
            if (songs == null) {
                processedArtistsLiveData.postValue(Collections.emptyList());
                return processedArtistsLiveData;
            }

            // 将聚合、拼音生成和排序操作放到后台线程
            databaseWriteExecutor.execute(() -> {
                Map<String, ArtistAggregator> artistAggregationMap = new HashMap<>();

                for (Song song : songs) {
                    if (song.getArtistName() != null && !song.getArtistName().isEmpty() &&
                            !Constants.UNKNOWN_STRING.equalsIgnoreCase(song.getArtistName())) {

                        String[] individualArtists = song.getArtistName().split("/"); // 拆分歌手名
                        for (String artistNamePart : individualArtists) {
                            String trimmedArtistName = artistNamePart.trim();
                            if (trimmedArtistName.isEmpty() || Constants.UNKNOWN_STRING.equalsIgnoreCase(trimmedArtistName)) {
                                continue;
                            }

                            ArtistAggregator aggregator = artistAggregationMap.get(trimmedArtistName);
                            if (aggregator == null) {
                                aggregator = new ArtistAggregator(trimmedArtistName, song.getArtistIdRoom()); // 使用第一个遇到的歌曲的artistIdRoom作为代表ID
                                artistAggregationMap.put(trimmedArtistName, aggregator);
                            }
                            aggregator.songCount++;
                            // 第一个遇到的非空专辑封面可以作为代表 (但我们决定不使用它作为歌手头像)
                            // if (aggregator.representativeAlbumArtUri == null && song.getAlbumArtUri() != null && !song.getAlbumArtUri().isEmpty()) {
                            //     aggregator.representativeAlbumArtUri = song.getAlbumArtUri();
                            // }
                        }
                    }
                }

                List<ArtistInfo> finalArtistInfoList = new ArrayList<>();
                for (ArtistAggregator aggregator : artistAggregationMap.values()) {
                    String pinyin = PinyinUtil.getPinyin(aggregator.artistName);
                    // representativeAlbumArtUri 始终为 null，因为我们决定不显示专辑封面作为歌手头像
                    finalArtistInfoList.add(new ArtistInfo(
                            aggregator.representativeArtistId,
                            aggregator.artistName,
                            aggregator.songCount,
                            pinyin,
                            null // representativeAlbumArtUri is null
                    ));
                }

                // 按拼音排序
                finalArtistInfoList.sort((o1, o2) -> {
                    if (o1.artistPinyin == null && o2.artistPinyin == null) return 0;
                    if (o1.artistPinyin == null) return 1;
                    if (o2.artistPinyin == null) return -1;
                    String firstChar1 = PinyinUtil.getFirstPinyinChar(o1.artistName);
                    String firstChar2 = PinyinUtil.getFirstPinyinChar(o2.artistName);
                    if (firstChar1.equals("#") && !firstChar2.equals("#")) return 1;
                    if (!firstChar1.equals("#") && firstChar2.equals("#")) return -1;
                    return o1.artistPinyin.compareToIgnoreCase(o2.artistPinyin);
                });

                processedArtistsLiveData.postValue(finalArtistInfoList);
            });
            return processedArtistsLiveData;
        });
    }

    /**
     * 获取所有独立歌手的摘要信息，并支持按歌手名搜索。
     * 结果按歌手名拼音排序。处理"歌手A/歌手B"格式。
     *
     * @param rawQuery (可选) 用户输入的原始歌手名搜索查询词 (不含通配符)。
     * @return LiveData 包装的 ArtistInfo 列表。
     */
    public LiveData<List<ArtistInfo>> getArtistsInfoFilteredOrAllSortedByPinyin(@Nullable String rawQuery) {
        String daoQueryWithWildcards = null;
        if (rawQuery != null && !rawQuery.trim().isEmpty()) {
            daoQueryWithWildcards = "%" + rawQuery.trim() + "%";
        }

        // 1. 从DAO获取基于查询的基础歌曲列表 (LiveData<List<Song>>)
        LiveData<List<Song>> songsForAggregationLiveData = songDao.getSongsForArtistAggregationLiveData(daoQueryWithWildcards);

        // 2. 使用 Transformations.map 在后台（由Room的LiveData查询保证）处理这个列表
        return Transformations.map(songsForAggregationLiveData, songs -> {
            Timber.d("Transforming songs list (size: %d) for artist aggregation.", songs != null ? songs.size() : 0);
            if (songs == null) {
                return Collections.emptyList();
            }

            // 用于聚合每个独立歌手信息的 Map
            // Key: 独立歌手名 (trimmed)
            // Value: ArtistAggregator 实例
            Map<String, ArtistAggregator> artistAggregationMap = new HashMap<>();

            for (Song song : songs) {
                if (song.getArtistName() == null || song.getArtistName().isEmpty() ||
                        Constants.UNKNOWN_STRING.equalsIgnoreCase(song.getArtistName())) {
                    continue; // 跳过未知或空歌手名的歌曲
                }

                // 拆分 "歌手A/歌手B" 格式的歌手名
                String[] individualArtists = song.getArtistName().split("/");
                for (String artistNamePart : individualArtists) {
                    String trimmedArtistName = artistNamePart.trim();
                    if (trimmedArtistName.isEmpty() || Constants.UNKNOWN_STRING.equalsIgnoreCase(trimmedArtistName)) {
                        continue; // 跳过空的或未知的拆分部分
                    }

                    ArtistAggregator aggregator = artistAggregationMap.get(trimmedArtistName);
                    if (aggregator == null) {
                        // 当第一次遇到这个歌手名时，创建一个新的聚合器
                        // 使用当前歌曲的 artistIdRoom (即 song.getArtistId()) 作为代表性的ID
                        aggregator = new ArtistAggregator(trimmedArtistName, song.getArtistIdRoom());
                        artistAggregationMap.put(trimmedArtistName, aggregator);
                    }
                    aggregator.songCount++; // 增加该歌手的歌曲计数
                    // representativeAlbumArtUri 根据之前的决定，不在这里设置
                }
            }

            // 将聚合结果转换为 List<ArtistInfo>
            List<ArtistInfo> finalArtistInfoList = new ArrayList<>();
            for (ArtistAggregator aggregator : artistAggregationMap.values()) {
                String pinyin = PinyinUtil.getPinyin(aggregator.artistName);
                finalArtistInfoList.add(new ArtistInfo(
                        aggregator.representativeArtistId,
                        aggregator.artistName,
                        aggregator.songCount,
                        pinyin,
                        null // representativeAlbumArtUri 设置为 null
                ));
            }

            // 按歌手名拼音排序 (之前提供的详细排序逻辑)
            finalArtistInfoList.sort((o1, o2) -> {
                if (o1.artistPinyin == null && o2.artistPinyin == null) return 0;
                if (o1.artistPinyin == null) return 1;
                if (o2.artistPinyin == null) return -1;

                String firstChar1 = PinyinUtil.getFirstPinyinChar(o1.artistName);
                String firstChar2 = PinyinUtil.getFirstPinyinChar(o2.artistName);

                if (firstChar1.equals("#") && !firstChar2.equals("#")) return 1;
                if (!firstChar1.equals("#") && firstChar2.equals("#")) return -1;
                if (firstChar1.equals("#") && firstChar2.equals("#")) {
                    return o1.artistName.compareToIgnoreCase(o2.artistName);
                }
                int pinyinCompare = o1.artistPinyin.compareToIgnoreCase(o2.artistPinyin);
                if (pinyinCompare != 0) {
                    return pinyinCompare;
                }
                return o1.artistName.compareToIgnoreCase(o2.artistName);
            });

            Timber.d("Finished artist aggregation. Result size: %d", finalArtistInfoList.size());
            return finalArtistInfoList;
        });
    }

    /**
     * 内部辅助类，用于聚合歌手信息。
     */
    private static class ArtistAggregator {
        String artistName;
        long representativeArtistId; // 用遇到的第一个歌曲的 artistIdRoom 作为代表
        int songCount;
        // String representativeAlbumArtUri; // 不再需要，因为我们不显示专辑封面作为歌手头像

        ArtistAggregator(String artistName, long representativeArtistId) {
            this.artistName = artistName;
            this.representativeArtistId = representativeArtistId;
            this.songCount = 0;
            // this.representativeAlbumArtUri = null;
        }
    }

    /**
     * 根据（可能是独立的）歌手名获取该歌手的所有歌曲。
     * 注意：如果歌曲的 artist_name 字段是 "歌手A/歌手B"，这个方法用 "歌手A" 去查询时，
     * 可能需要 LIKE '%歌手A%' 或者在 Repository 中做进一步处理。
     * 为了简化，我们先假设 getSongsByArtistName 在DAO层面能处理独立歌手名。
     * 如果不能，ArtistSongsActivity 将会显示包含这个歌手名的所有歌曲（包括合作歌曲）。
     *
     * @param artistName 歌手名。
     * @return LiveData 包装的歌曲列表。
     */
    public LiveData<List<Song>> getSongsByArtistName(String artistName) {
        // 为了能匹配到 "歌手A/歌手B/歌手C" 中包含 "歌手B" 的情况，
        // 我们需要使用 LIKE 查询。
        // SongDao 需要一个支持 LIKE 的新方法。
        return songDao.getSongsByArtistNameLike(artistName); // 假设 SongDao 有此方法
    }

    // --- Album List Operations (包括搜索) ---

    /**
     * 获取所有专辑的摘要信息，并处理艺术家名、拼音和封面。
     * 结果按专辑名拼音排序。
     *
     * @return LiveData 包装的 AlbumInfo 列表。
     */
    public LiveData<List<AlbumInfo>> getAllAlbumsWithInfoSortedByPinyin() {
        LiveData<List<SongDao.AlbumInfoQueryResult>> rawAlbumData = songDao.getAlbumSummaries();

        return Transformations.switchMap(rawAlbumData, queryResults -> {
            MutableLiveData<List<AlbumInfo>> processedLiveData = new MutableLiveData<>();
            if (queryResults == null) {
                processedLiveData.postValue(Collections.emptyList());
                return processedLiveData;
            }

            databaseWriteExecutor.execute(() -> {
                List<AlbumInfo> albumInfoList = new ArrayList<>();
                for (SongDao.AlbumInfoQueryResult result : queryResults) {
                    String finalArtistName;
                    // 1. 优先使用 AlbumArtist 标签 (如果存在且有效)
                    if (result.albumArtistLabel != null && !result.albumArtistLabel.isEmpty() &&
                            !Constants.UNKNOWN_STRING.equalsIgnoreCase(result.albumArtistLabel) &&
                            !result.albumArtistLabel.equalsIgnoreCase("Various Artists") && // "Various Artists" 也视为需要拼接
                            !result.albumArtistLabel.equalsIgnoreCase("合集")) { // 常见合辑标记
                        finalArtistName = result.albumArtistLabel.trim();
                    } else {
                        // 2. 如果 AlbumArtist 无效，则获取该专辑所有歌曲，提取并拼接独立艺术家
                        List<Song> songsInAlbum = songDao.getSongsByAlbumId_internal(result.albumId);
                        if (songsInAlbum != null && !songsInAlbum.isEmpty()) {
                            Set<String> uniqueArtistNames = new LinkedHashSet<>(); // 使用 LinkedHashSet 保持顺序并去重
                            for (Song song : songsInAlbum) {
                                if (song.getArtistName() != null && !song.getArtistName().isEmpty() &&
                                        !Constants.UNKNOWN_STRING.equalsIgnoreCase(song.getArtistName())) {
                                    String[] individualArtists = song.getArtistName().split("/");
                                    for (String artistPart : individualArtists) {
                                        String trimmedPart = artistPart.trim();
                                        if (!trimmedPart.isEmpty() && !Constants.UNKNOWN_STRING.equalsIgnoreCase(trimmedPart)) {
                                            uniqueArtistNames.add(trimmedPart);
                                        }
                                    }
                                }
                            }
                            if (!uniqueArtistNames.isEmpty()) {
                                finalArtistName = String.join(" / ", uniqueArtistNames);
                            } else {
                                // 如果所有歌曲的艺术家都未知，则使用 AlbumInfoQueryResult 中的代表艺术家名
                                finalArtistName = result.representativeArtistName != null ? result.representativeArtistName : Constants.UNKNOWN_STRING;
                            }
                        } else {
                            // 如果专辑下没有歌曲（理论上不应发生，因为聚合基于歌曲表）
                            // 或无法获取歌曲，则使用 AlbumInfoQueryResult 中的代表艺术家名
                            finalArtistName = result.representativeArtistName != null ? result.representativeArtistName : Constants.UNKNOWN_STRING;
                        }
                    }

                    // 如果拼接后或使用albumArtist后仍然是"未知"，则统一为 Constants.UNKNOWN_STRING
                    if (TextUtils.isEmpty(finalArtistName) || finalArtistName.equalsIgnoreCase(Constants.UNKNOWN_STRING)) {
                        finalArtistName = Constants.UNKNOWN_STRING;
                    }


                    String pinyin = PinyinUtil.getPinyin(result.albumName);
                    String coverUri = result.albumArtUri; // DAO查询已包含一个代表性封面

                    albumInfoList.add(new AlbumInfo(result.albumId, result.albumName, finalArtistName, result.songCount, coverUri, pinyin));
                }

                // 按专辑拼音排序
                albumInfoList.sort((o1, o2) -> {
                    if (o1.albumPinyin == null && o2.albumPinyin == null) return 0;
                    if (o1.albumPinyin == null) return 1;
                    if (o2.albumPinyin == null) return -1;
                    String firstChar1 = PinyinUtil.getFirstPinyinChar(o1.albumName);
                    String firstChar2 = PinyinUtil.getFirstPinyinChar(o2.albumName);
                    if (firstChar1.equals("#") && !firstChar2.equals("#")) return 1;
                    if (!firstChar1.equals("#") && firstChar2.equals("#")) return -1;
                    return o1.albumPinyin.compareToIgnoreCase(o2.albumPinyin);
                });

                processedLiveData.postValue(albumInfoList);
            });
            return processedLiveData;
        });
    }

    /**
     * 获取所有专辑的摘要信息，并支持按专辑名搜索。
     * 结果按专辑名拼音排序。
     *
     * @param query (可选) 用户输入的原始专辑名搜索查询词。
     * @return LiveData 包装的 AlbumInfo 列表。
     */
    public LiveData<List<AlbumInfo>> getAlbumsInfoFilteredOrAllSortedByPinyin(@Nullable String query) {
        String daoQuery = null;
        if (query != null && !query.trim().isEmpty()) {
            daoQuery = "%" + query.trim() + "%";
        }
        LiveData<List<SongDao.AlbumInfoQueryResult>> rawAlbumData = songDao.getAlbumSummariesFiltered(daoQuery);

        // 这里的转换逻辑与你之前在 SongRepository 中为 getAllAlbumsWithInfoSortedByPinyin
        // 实现的非常相似，主要是数据源 (rawAlbumData) 现在是过滤后的。
        return Transformations.switchMap(rawAlbumData, queryResults -> {
            MutableLiveData<List<AlbumInfo>> processedLiveData = new MutableLiveData<>();
            if (queryResults == null) {
                processedLiveData.postValue(Collections.emptyList());
                return processedLiveData;
            }
            databaseWriteExecutor.execute(() -> {
                List<AlbumInfo> albumInfoList = new ArrayList<>();
                for (SongDao.AlbumInfoQueryResult result : queryResults) {
                    String finalArtistName = determineFinalArtistName(result.albumId, result.representativeArtistName); // 使用辅助方法
                    String pinyin = PinyinUtil.getPinyin(result.albumName);
                    albumInfoList.add(new AlbumInfo(result.albumId, result.albumName, finalArtistName, result.songCount, result.albumArtUri, pinyin));
                }
                albumInfoList.sort((o1, o2) -> { /* ... (你的专辑拼音排序逻辑) ... */
                    if (o1.albumPinyin == null && o2.albumPinyin == null) return 0;
                    if (o1.albumPinyin == null) return 1;
                    if (o2.albumPinyin == null) return -1;
                    // ... (完整排序逻辑)
                    return o1.albumPinyin.compareToIgnoreCase(o2.albumPinyin);
                });
                processedLiveData.postValue(albumInfoList);
            });
            return processedLiveData;
        });
    }

    // 辅助方法来确定专辑的最终艺术家名称 (与你之前版本类似)
    private String determineFinalArtistName(long albumId, String representativeArtistNameFromQuery) {
        // 优先使用 AlbumArtist 标签 (如果 Song 实体有，并且 AlbumInfoQueryResult 也返回了它)
        // 假设 Song 实体没有 album_artist，我们需要从该专辑的歌曲中聚合艺术家
        List<Song> songsInAlbum = songDao.getSongsByAlbumId_internal(albumId); // 同步获取
        if (songsInAlbum != null && !songsInAlbum.isEmpty()) {
            Set<String> uniqueArtistNames = new LinkedHashSet<>();
            for (Song song : songsInAlbum) {
                if (song.getArtistName() != null && !song.getArtistName().isEmpty() &&
                        !Constants.UNKNOWN_STRING.equalsIgnoreCase(song.getArtistName())) {
                    String[] individualArtists = song.getArtistName().split("/");
                    for (String artistPart : individualArtists) {
                        String trimmedPart = artistPart.trim();
                        if (!trimmedPart.isEmpty() && !Constants.UNKNOWN_STRING.equalsIgnoreCase(trimmedPart)) {
                            uniqueArtistNames.add(trimmedPart);
                        }
                    }
                }
            }
            if (!uniqueArtistNames.isEmpty()) {
                return String.join(" / ", uniqueArtistNames);
            }
        }
        // 如果都失败，回退到查询结果中的代表歌手名，或未知
        return representativeArtistNameFromQuery != null ? representativeArtistNameFromQuery : Constants.UNKNOWN_STRING;
    }


    // `getSongsByAlbumId` 方法现在在DAO层返回 LiveData<List<Song>>，可以直接在Repository中暴露
    public LiveData<List<Song>> getSongsByAlbumId(long albumId) {
        return songDao.getSongsByAlbumId(albumId);
    }

    // --- Folder List Operations ---

    /**
     * 获取所有音乐文件夹的信息 (路径、名称、歌曲数量)，按文件夹名称排序。
     *
     * @return LiveData 包装的 FolderInfo 列表。
     */
    public LiveData<List<FolderInfo>> getMusicFoldersSortedByName() {
        LiveData<List<SongDao.FolderPathWithCount>> rawFolderData = songDao.getFolderPathsWithSongCounts();

        return Transformations.map(rawFolderData, folderPathCounts -> {
            if (folderPathCounts == null) {
                return Collections.emptyList();
            }
            List<FolderInfo> folderInfoList = new ArrayList<>();
            for (SongDao.FolderPathWithCount pathCount : folderPathCounts) {
                if (pathCount.folderPath != null && !pathCount.folderPath.isEmpty()) {
                    String folderName = new File(pathCount.folderPath).getName(); // 从完整路径获取文件夹名
                    if (folderName.isEmpty() && pathCount.folderPath.equals("/")) { // 根目录特殊处理
                        folderName = "根目录存储"; // 或者其他合适的名称
                    } else if (folderName.isEmpty()) {
                        folderName = "未知文件夹"; // 以防万一
                    }
                    folderInfoList.add(new FolderInfo(pathCount.folderPath, folderName, pathCount.songCount));
                }
            }

            // 再次排序以确保是按 folderName (而不是 folderPath) 排序，如果需要的话
            // DAO层面已按 folder_path 排序，如果 folderName 的排序与 folderPath 不同，则需要在这里重排
            // 为简单起见，先依赖DAO的排序。如果需要按显示的 folderName 排序，则：
            // folderInfoList.sort((f1, f2) -> f1.folderName.compareToIgnoreCase(f2.folderName));
            // 这里DAO已经按path排序了，通常路径名和文件夹名排序结果类似或用户可以接受

            return folderInfoList;
        });
    }

    /**
     * 根据文件夹路径获取该文件夹下的所有歌曲。
     *
     * @param folderPath 文件夹路径。
     * @return LiveData 包装的歌曲列表。
     */
    public LiveData<List<Song>> getSongsInFolderPath(String folderPath) {
        return songDao.getSongsInFolderPath(folderPath);
    }

    /**
     * 获取所有音乐文件夹的信息，并支持按文件夹名搜索。
     * 结果按文件夹名称排序。
     *
     * @param query (可选) 用户输入的原始文件夹名搜索查询词。
     * @return LiveData 包装的 FolderInfo 列表。
     */
    public LiveData<List<FolderInfo>> getMusicFoldersFilteredOrAllSortedByName(@Nullable String query) {
        String daoPathQuery = null; // DAO层面仍然基于path进行LIKE，后续在Repository过滤folderName
        if (query != null && !query.trim().isEmpty()) {
            // 为了能匹配路径中的任何部分（如果需要），或者只匹配末尾的文件夹名
            // 如果只匹配文件夹名，这里的 daoPathQuery 应该更智能，或者在后面过滤
            // 为了让LIKE对路径有效，可以先这样
            daoPathQuery = "%" + query.trim() + "%";
        }

        LiveData<List<SongDao.FolderPathWithCount>> rawFolderData = songDao.getFolderPathsWithCountsFiltered(daoPathQuery);

        return Transformations.map(rawFolderData, folderPathCounts -> {
            if (folderPathCounts == null) {
                return Collections.emptyList();
            }
            List<FolderInfo> folderInfoList = new ArrayList<>();
            String trimmedQuery = (query != null) ? query.trim().toLowerCase() : null;

            for (SongDao.FolderPathWithCount pathCount : folderPathCounts) {
                if (pathCount.folderPath != null && !pathCount.folderPath.isEmpty()) {
                    String folderName = new File(pathCount.folderPath).getName();
                    if (folderName.isEmpty() && pathCount.folderPath.equals("/")) {
                        folderName = "根目录存储";
                    } else if (folderName.isEmpty()) {
                        folderName = "未知文件夹";
                    }

                    // 如果有搜索查询，并且要求只匹配 folderName，则在这里进行二次过滤
                    if (trimmedQuery != null && !trimmedQuery.isEmpty()) {
                        if (folderName.toLowerCase().contains(trimmedQuery)) {
                            folderInfoList.add(new FolderInfo(pathCount.folderPath, folderName, pathCount.songCount));
                        }
                    } else {
                        // 没有搜索查询，全部添加
                        folderInfoList.add(new FolderInfo(pathCount.folderPath, folderName, pathCount.songCount));
                    }
                }
            }

            // 按 folderName 排序
            folderInfoList.sort((f1, f2) -> {
                if (f1.folderName == null && f2.folderName == null) return 0;
                if (f1.folderName == null) return 1;
                if (f2.folderName == null) return -1;
                // 简单的字典序，如果需要拼音，也需要 PinyinUtil
                return f1.folderName.compareToIgnoreCase(f2.folderName);
            });
            return folderInfoList;
        });
    }


    // --- Recently Played Song Operations ---

    /**
     * 添加或更新一首歌曲到最近播放列表。
     * 如果列表超过上限，会自动移除最旧的记录。
     *
     * @param songId 要添加或更新的歌曲ID。
     */
    public void addOrUpdateRecentPlay(long songId) {
        databaseWriteExecutor.execute(() -> {
            RecentlyPlayedSong recentPlay = new RecentlyPlayedSong(songId, System.currentTimeMillis());
            recentlyPlayedDao.addOrUpdateRecentPlay(recentPlay);
            Timber.d("Song ID %d added/updated in recent plays.", songId);

            // 检查并清理超出上限的记录
            int currentCount = recentlyPlayedDao.getRecentPlaysCount();
            if (currentCount > Constants.RECENT_PLAY_LIST_LIMIT) { // RECENT_PLAY_LIST_LIMIT 需要在Constants中定义
                int itemsToDelete = currentCount - Constants.RECENT_PLAY_LIST_LIMIT;
                for (int i = 0; i < itemsToDelete; i++) {
                    long oldestId = recentlyPlayedDao.getOldestPlayedSongId();
                    if (oldestId != 0) { // 确保有记录可删
                        recentlyPlayedDao.deleteRecentPlayBySongId(oldestId);
                        Timber.d("Removed oldest recent play entry (Song ID: %d) to maintain limit.", oldestId);
                    } else {
                        break; // 没有更多可删的了
                    }
                }
            }
        });
    }

    /**
     * 获取最近播放的歌曲列表 (完整的Song对象)。
     *
     * @return LiveData 包装的歌曲列表。
     */
    public LiveData<List<Song>> getRecentlyPlayedSongsWithDetails() {
        return recentlyPlayedDao.getRecentlyPlayedSongsWithDetails(Constants.RECENT_PLAY_LIST_LIMIT);
    }

    /**
     * 清空所有最近播放记录。
     */
    public void clearAllRecentPlays() {
        databaseWriteExecutor.execute(() -> {
            recentlyPlayedDao.clearAllRecentPlays();
            Timber.i("All recent plays cleared.");
        });
    }

    // --- Search Operations ---

    /**
     * 根据关键词搜索歌曲。
     *
     * @param query 用户输入的搜索查询词 (不含通配符)。
     * @return LiveData 包装的匹配歌曲列表。
     */
    public LiveData<List<Song>> searchSongs(String query) {
        if (query == null || query.trim().isEmpty()) {
            return songDao.getAllSongsSortedByPinyin();
        }
        // 在调用DAO之前，为查询词添加模糊匹配的通配符
        String searchQuery = "%" + query.trim() + "%";
        return songDao.searchSongs(searchQuery);
    }

    // --- Play Count Operations ---
    /**
     * 增加指定歌曲的播放次数。
     * @param songId 歌曲ID。
     */
    public void incrementPlayCount(long songId) {
        databaseWriteExecutor.execute(() -> {
            playCountDao.insertOrIncrement(songId); // 调用DAO的事务方法
            Timber.d("Incremented play count for song ID: %d", songId);
        });
    }

    /**
     * 获取所有被播放过的歌曲及其播放次数。
     * @return LiveData 包装的 SongWithPlayCount DTO 列表。
     */
    public LiveData<List<PlayCountDao.SongWithPlayCount>> getSongsWithPlayCounts() {
        return playCountDao.getSongsWithPlayCounts();
    }

    /**
     * 清空所有播放统计。
     */
    public void clearAllPlayCounts() {
        databaseWriteExecutor.execute(playCountDao::clearAll);
        Timber.i("All play counts cleared.");
    }
}
